<script lang="ts" setup>
import type { Dict } from '@croco/framework/types';

import type { Menu } from './data';

import { nextTick, onBeforeMount, reactive, ref, watch } from 'vue';

import { VIcon } from '@croco/framework/icons';
import { Page } from '@croco/framework/libraries';

import { getDictTrim, getMenuTree } from '#/api';
import { service } from '#/api/request';

import { useDataTemplate } from './data';
import Edit from './edit.vue';

defineOptions({ name: 'SystemMenu' });

const menuRef = ref();
const editRef = ref();
const mainRef = ref();

const menuLoading = ref(false);
const currentMenu = ref<Menu>({});
const menuProps = reactive({
    label: (data: any) => {
        return data.title;
    },
    class: (data: any) => {
        return data.id === 0 ? 'el-tree-node__plus' : '';
    },
});
const { menuDataTemplate } = useDataTemplate();

const enums = reactive<{
    choice: Array<Dict>;
    menu: Array<Menu>;
    type: Array<Dict> | undefined;
}>({
    choice: [],
    menu: [],
    type: undefined,
});

// 树点击
const onCurrentChange = (data: Menu) => {
    if (data) {
        currentMenu.value = data;
        mainRef.value.$el.scrollTop = 0;
    } else {
        currentMenu.value = {};
    }
};

// 树过滤
const menuFilterText = ref('');
const menuFilterNode = (value: any, data: any) => {
    if (!value) return true;
    return data.title.includes(value);
};
watch(menuFilterText, (val) => menuRef.value?.filter(val));

// 刷新
const onRefreshMenuTree = () => {
    menuFilterText.value = '';
    menuLoading.value = true;
    getMenuTree('D,C,W')
        .then(({ data }) => {
            enums.menu = data;
            if (enums.menu.length > 0) {
                nextTick(() => menuRef.value.setCurrentKey(currentMenu.value.id ?? enums.menu[0]?.id));
            }
        })
        .finally(() => (menuLoading.value = false));
};

// 增加
const onCreate = async (data = currentMenu.value) => {
    const order: number = (data.children?.at(-1)?.sequence ?? 0) + 5;
    // 遍历 enums.type 对象,获取默认值
    let type = '';
    for (const value of Object.values(enums.type || {})) {
        if (value.isDefault === 'Y') {
            type = value.value;
        }
    }
    onSave({
        ...menuDataTemplate,
        name: data.name ?? '',
        parentId: data?.id ?? 0,
        path: data?.path ? `${data.path}/` : '',
        sequence: order,
        type,
    });
};

// 新增&修改 菜单/按钮信息
const onSave = (form: Menu) => {
    service[form.id ? 'put' : 'post']('/system/menu', form).then(({ data }) => {
        if (form.id) {
            // 位置发生变化时需刷新菜单树，其他情况只要跟新节点数据即可，避免不必要的后端请求
            if (form.parentId !== currentMenu.value.parentId || form.sequence !== currentMenu.value.sequence) {
                onRefreshMenuTree();
            } else {
                const node = menuRef.value.getNode(form.id);
                Object.assign(node.data, data);
            }
        } else {
            // 追加根节点/子节点，并选中当前新节点
            menuRef.value.append(data, data.parentId);
            menuRef.value.setCurrentKey(data.id);
        }
    });
};

// 删除菜单
const onDelete = (data: Menu) => {
    service.confirm({
        message: `确定对菜单[${data.title}]包含子菜单进行删除操作?`,
        url: '/system/menu',
        data: { id: [data.id] },
        success: () => {
            menuRef.value.remove(data.id);
            // 删除当前菜单时则需要将编辑表单重置，并重新选中其他节点
            if (data.id === currentMenu.value.id) {
                currentMenu.value = {};
                menuRef.value.setCurrentKey(enums.menu[0]?.id);
            }
        },
    });
};

onBeforeMount(() => {
    getDictTrim(['sys_menu_type', 'sys_yes_no'])
        .then((rs) => {
            enums.type = rs[0] ?? [];
            enums.choice = (rs[1] ?? []).map((item: any) => {
                item.value = Number(item.value);
                return item;
            });
        })
        .then(() => {
            onRefreshMenuTree();
        });
});
</script>

<template>
    <Page auto-content-height>
        <el-container>
            <el-aside width="400px">
                <el-container>
                    <el-header>
                        <el-input placeholder="请输入菜单名称进行过滤" v-model="menuFilterText" clearable />
                        <el-button @click="onRefreshMenuTree()" style="margin-left: 6px">
                            <template #icon>
                                <VIcon icon="icon:refresh" />
                            </template>
                        </el-button>
                    </el-header>
                    <el-main v-loading="menuLoading" style="padding: 0">
                        <el-tree
                            ref="menuRef"
                            :accordion="false"
                            :check-strictly="true"
                            :data="enums.menu"
                            :expand-on-click-node="true"
                            :filter-node-method="menuFilterNode"
                            :highlight-current="true"
                            :props="menuProps"
                            class="menu"
                            node-key="id"
                            @current-change="onCurrentChange"
                        >
                            <template #default="{ node, data }">
                                <span class="custom-tree-node el-tree-node__label">
                                    <span class="label">
                                        <VIcon :icon="data.icon" />
                                        <span style="margin-left: 5px">{{ node.label }}</span>
                                    </span>
                                    <span class="do">
                                        <el-button v-if="data.type !== 'F'" v-auth="'system:menu:remove'" link type="danger" @click.stop="onDelete(data)" />
                                    </span>
                                </span>
                            </template>
                        </el-tree>
                    </el-main>
                    <el-footer>
                        <el-button v-auth="'system:menu:add'" style="width: 100%" link @click="onCreate()" />
                    </el-footer>
                </el-container>
            </el-aside>
            <el-container>
                <el-main ref="mainRef" class="kt-edit-main" style="padding: 20px">
                    <Edit ref="editRef" :save="onSave" :enums="enums" :menu="currentMenu" />
                </el-main>
            </el-container>
        </el-container>
    </Page>
</template>
<style scoped>
.el-container {
    height: 100%;
    .el-aside {
        background-color: var(--el-fill-color-blank);
        border-right: 1px dashed var(--el-border-color);
        .el-header {
            height: 50px;
            display: flex;
            justify-content: center;
            align-items: center;
            border-bottom: 1px dashed var(--el-border-color);
        }
        .el-footer {
            display: flex;
            height: 42px;
            border-top: 1px dashed var(--el-border-color);
        }
    }

    .kt-edit-main {
        background-color: var(--el-fill-color-blank);
    }
}

.el-tree {
    --el-tree-node-content-height: 30px;
}

.custom-tree-node {
    display: flex;
    flex: 1;
    align-items: center;
    justify-content: space-between;
    font-size: 15px;
    padding-right: 24px;
    height: 100%;
}

.custom-tree-node .label {
    display: flex;
    align-items: center;
    height: 100%;
}

.custom-tree-node .label .el-tag {
    margin-left: 5px;
}

.custom-tree-node .do {
    display: none;
}

.custom-tree-node:hover .do {
    display: inline-block;
}

.el-tree-node__plus .custom-tree-node {
    justify-content: center;
}
</style>
